<?php
/**
 * 
 * Copyright (c) 2008 Jerry Jalava <jerry.jalava@gmail.com>
 * Licensed under the GPLv3 license
 * http://www.gnu.org/licenses/gpl.html
 * 
 */

class couchdb_views
{
    private $configuration;
    private $documents;
    
    public function __construct(&$configuration)
    {
        $this->configuration =& $configuration;
        
        $this->documents = new couchdb_documents($this->configuration);
    }
    
    public function __get($name)
    {
        return $this->execute($name);
    }
    
    public function __set($name, $value)
    {
        if ($value === false)
        {
            return $this->remove($name);
        }
        
        $results = $this->update($name, $value);
        
        if (   !isset($results->ok)
            || !$results->ok)
        {
            $reason = '';
            if (   isset($results->error)
                && isset($results->reason))
            {
                $reason = "CouchDB said error: '{$results->error}', reason: '{$results->reason}'";
            }
            
            throw new couchdb_view_exception("Couldn't save view {$name}. {$reason}");
        }
    }
    
    public function __isset($name)
    {
        return $this->exists($name);
    }
    
    public function temp($function, $args=null)
    {
        $view = new couchdb_views_view('_temp_view', $this->configuration);
        $view->set_args($function);

        if (! is_null($args))
        {
            $view->set_args($args);            
        }
        
        $results = $view->run();
        if (isset($results->rows))
        {
            $results->rows = $this->documents->convert($results->rows);
        }
        
        return $results;
    }
    
    public function create($name, $value)
    {
        return $this->update($name, $value);
    }

    public function delete($name)
    {
        return false;
    }
    
    public function execute($name, $args=null)
    {        
        $this->exists($name);

        $view = new couchdb_views_view($name, $this->configuration);
        $view->set_args($args);

        $results = $view->run();
        if (isset($results->rows))
        {
            $results->rows = $this->documents->convert($results->rows);
        }
        
        return $results;
    }
    
    public function update($name, $value)
    {
        $update_only_view = false;
        
        if (strpos($name, '/') !== false)
        {
            $name_parts = explode('/', $name);
            $name = $name_parts[0];
            $update_only_view = $name_parts[1];
            $new_view = $value;
        }
            
        $view = new couchdb_views_view($name, $this->configuration);

        $existing_view = null;        
        if ($this->exists($name, true))
        {            
            $existing_view = $view->get();            
        }
        
        if ($update_only_view)
        {
            if (is_null($existing_view))
            {
                throw new couchdb_view_exception("View {$name} doesn't exist! Cannot update.");
            }
                        
            $value = array
            (
                '_rev' => $existing_view->_rev,
                'language' => $existing_view->language,
                'views' => get_object_vars($existing_view->views)
            );
            $value['views'][$update_only_view] = $new_view;
            
            $view->set_args($value);

            return $view->run(true);
        }
        
        if (   !is_null($existing_view)
            && isset($existing_view->_rev))
        {
            $value['_rev'] = $existing_view->_rev;
        }
        
        if (! isset($value['language']))
        {
            $value['language'] = 'text/javascript';

            if (   !is_null($existing_view)
                && isset($existing_view->language))
            {
                $value['language'] = $existing_view->language;
            }
        }
        
        $view->set_args($value);
        
        return $view->run(true);
    }
    
    private function exists($name, $graceful=false)
    {
        try
        {
            $view = new couchdb_views_view($name, $this->configuration);
            $view->exists();
            
            return true;
        }
        catch(couchdb_view_exception $e)
        {
            if ($graceful)
            {
                return false;
            }
            
            if ($e->getCode() == 404)
            {
                throw new couchdb_view_exception("View '{$name}' doesn't exist!");
            }

            throw $e;
        }
        
        return false;
    }
    
    public function clear_caches()
    {
    }
}

?>